﻿using System;
using System.Collections.Generic;
using System.Linq;
using EzDesk.Core.Model;
using EzDesk.EzAppApi.Utility.CoreAppService;
using EzDesk.Utility.ServiceReference;

namespace EzDesk.EzAppApi.Utility
{
    // 客户端App使用AppService的帮助类
    // todo: 解决好Faulted State的问题
    public partial class CacheableEzApiClient : IEzApiClient
    {
        #region Singleton

        public static readonly EzApiClient Instance = new EzApiClient();

        private CacheableEzApiClient()
        {
        }

        private static ICoreAppService CoreAppService
        {
            get { return ServiceReferenceFactory<ICoreAppService, CoreAppServiceClient>.GetService(); }
        }

        #endregion

        private const string SimpleUserCachePoolName = "SimpleUser";

        private readonly CachePoolCollection _cache = new CachePoolCollection();

        #region Users

        public SimpleUser GetSimpleUserById(Guid userId)
        {
            return _cache.Get<Guid, SimpleUser>(SimpleUserCachePoolName)
                .Retrieve(userId, p => CoreAppService.GetSimpleUserById(p));
        }

        public IList<SimpleUser> GetSimpleUserInfos(string memberstring)
        {
            return _cache.Get<string, IList<SimpleUser>>("GetSimpleUserInfos")
                .Retrieve(memberstring, p => CoreAppService.GetSimpleUserInfos(p));
        }

        // No cache.
        public UserProfile GetUserProfileById(Guid userId)
        {
            return _cache.Get<Guid, UserProfile>("GetUserProfileById")
                .Retrieve(userId, p => CoreAppService.GetUserProfileById(p));
        }

        public IList<UserProfile> GetUserProfiles(string memberstring)
        {
            return _cache.Get<string, IList<UserProfile>>("GetUserProfiles")
                .Retrieve(memberstring, p => CoreAppService.GetUserProfiles(p));
        }

        // Not cacheable
        public Guid? CreateNewUser(UserProfile newUserProfile, string newPassword)
        {
            return CoreAppService.CreateNewUser(newUserProfile, newPassword);
        }

        // Not cacheable
        public void UpdateUserProfile(UserProfile userProfile)
        {
            CoreAppService.UpdateUserProfile(userProfile);
        }

        // Not cacheable
        public void ChangePassword(Guid userId, string oldPassword, string newPassword)
        {
            CoreAppService.ChangePassword(userId, oldPassword, newPassword);
        }

        public IList<SimpleUser> GetAllUsersByMemberString(string memberString)
        {
            return _cache.Get<string, IList<SimpleUser>>("GetAllUsersByMemberString")
                .Retrieve(memberString, p => CoreAppService.GetAllUsersByMemberString(p));
        }

        public IDictionary<Guid, string> GetChildrenByMemberString(string memberString)
        {
            return _cache.Get<string, IDictionary<Guid, string>>("GetChildrenByMemberString")
                .Retrieve(memberString, p => CoreAppService.GetChildrenByMemberString(p));
        }

        #endregion

        #region Depts

        public IList<Dept> GetAllDepts()
        {
            return GetDeptCache().Values.ToArray();
        }

        public Dept GetDeptById(Guid id)
        {
            return GetDeptCache()[id];
        }

        private IDictionary<Guid, Dept> GetDeptCache()
        {
            return _cache.Get<Guid, IDictionary<Guid, Dept>>("Dept")
                .Retrieve(Guid.Empty, p => CoreAppService.GetAllDepts().ToDictionary(q => q.Id));
        }

        #endregion

        #region Groups

        public Group GetGroupById(Guid groupId)
        {
            return _cache.Get<Guid, Group>().Retrieve(groupId,
                p => CoreAppService.GetGroupById(p));
        }

        public IList<Group> GetGroups(string groupIdStrs)
        {
            return _cache.Get<string, IList<Group>>().Retrieve(groupIdStrs,
                p => CoreAppService.GetGroups(p));
        }

        public Group GetGroupByName(string groupName)
        {
            return _cache.Get<string, Group>().Retrieve(groupName,
                p => CoreAppService.GetGroupByName(p));
        }

        public IList<Group> GetAllSystemGroups()
        {
            return _cache.Get<string, IList<Group>>().Retrieve(string.Empty,
                p => CoreAppService.GetAllSystemGroups());
        }

        public Group GetSystemGroup(string sysGroupName)
        {
            return _cache.Get<string, Group>().Retrieve(sysGroupName,
                p => CoreAppService.GetSystemGroup(p));
        }

        #endregion

        #region Feeds

        public void UpdateFeedData(Guid updateFeedId, string newFeedData)
        {
            CoreAppService.UpdateFeedData(updateFeedId, newFeedData);
        }

        public void SetFeedIsAvailable(Guid feedId, string memberString, bool isAvailable)
        {
            CoreAppService.SetFeedIsAvailable(feedId, memberString, isAvailable);
        }

        public void SetFeedsIsAvailable(string feedIdStrs, string memberstring, bool isAvailable)
        {
            CoreAppService.SetFeedsIsAvailable(feedIdStrs, memberstring, isAvailable);
        }

        public void UpdateFeedsData(string feedIdsStr, string updateDataStr)
        {
            CoreAppService.UpdateFeedsData(feedIdsStr, updateDataStr);
        }

        public void UpdatePersonalFeedData(Guid feedId, string memberstring, string feedDataEx)
        {
            CoreAppService.UpdatePersonalFeedData(feedId, memberstring, feedDataEx);
        }

        public void SetFeedRecord(Guid identity, string templateName, string memberstring, Guid feedId,
            string ignoreUsers)
        {
            CoreAppService.SetFeedRecord(identity, templateName, memberstring, feedId, ignoreUsers);
        }

        public string GetFeedRecord(Guid identity, string templateName, string userId)
        {
            return CoreAppService.GetFeedRecord(identity, templateName, userId);
        }

        public void UpdatePersonalFeedType(Guid feedId, string memberstring, string feedTypeStr)
        {
            CoreAppService.UpdatePersonalFeedType(feedId, memberstring, feedTypeStr);
        }

        public Guid SendFeed(string templateName, string feedData, string memberString, Guid? senderId,
            string ignoreUsers, bool isAvailable)
        {
            return CoreAppService.SendFeedByName(templateName, feedData, memberString, senderId, ignoreUsers,
                isAvailable);
        }

        public void SetFeedIsRead(Guid feedId, string memberstring, bool isRead)
        {
            CoreAppService.SetFeedIsRead(feedId, memberstring, isRead);
        }

        public void SetFeedsIsRead(string feedIdStrs, string memberstring, bool isRead)
        {
            CoreAppService.SetFeedsIsRead(feedIdStrs, memberstring, isRead);
        }

        #endregion

        #region Permissions

        public bool UserHasPermission(string permissionStr, Guid userId)
        {
            return _cache.Get<Tuple<string, Guid>, bool>().Retrieve(
                Tuple.Create(permissionStr, userId),
                p => CoreAppService.UserHasPermission(p.Item1, p.Item2));
        }

        public bool GroupHasPermission(string permissionStr, Guid groupId)
        {
            return _cache.Get<Tuple<string, Guid>, bool>().Retrieve(
                Tuple.Create(permissionStr, groupId),
                p => CoreAppService.GroupHasPermission(p.Item1, p.Item2));
        }

        #endregion

        #region HeadIcons

        public void UpdateHeadIcon(Guid userId, byte[] iconData, string iconType)
        {
            CoreAppService.UpdateHeadIcon(userId, iconData, iconType);
        }

        public UserHeadImage GetHeadIcon(Guid userId)
        {
            return _cache.Get<Guid, UserHeadImage>().Retrieve(userId,
                p => CoreAppService.GetHeadIcon(p));
        }

        #endregion

        public Organization GetOrganizationInfo()
        {
            return _cache.Get<string, Organization>().Retrieve(string.Empty,
                p => CoreAppService.GetOrganizationInfo());
        }
    }
}